/**
 * 
 */
package project;

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Semaphore;


/**
 * @author Edward Dinki
 * 
 */
public class Employee extends Thread {
	private CyclicBarrier teamBarrier;
	private CyclicBarrier manBarrier;
	private final boolean isLead;
	private final Manager myManager;
	private final Employee myLeader;
	private final int teamNum;
	private final int employeeNum;
	private int lunch;
	private int arrival;
	private final Semaphore teamRoom;
	private final Random rGen = new Random();
	private final int qChance = 5;
	private final SimulationStatistics stats;

	public Employee(Semaphore teamRoom, CyclicBarrier manBarrier, CyclicBarrier teamBarrier,
			boolean isLead, Manager myManager, Employee myLeader, int teamNum,
			int employeeNum, SimulationStatistics stats) {

		this.manBarrier = manBarrier;
		this.teamBarrier = teamBarrier;
		this.isLead = isLead;
		this.myManager = myManager;
		this.myLeader = myLeader;
		this.teamNum = teamNum;
		this.employeeNum = employeeNum;
		this.teamRoom = teamRoom;
		this.stats = stats;
	}

	public Employee(CyclicBarrier teamBarrier, boolean isLead,
			Manager myManager, Employee myLeader, int teamNum, int employeeNum, SimulationStatistics stats) {
		this.teamBarrier = teamBarrier;
		this.isLead = isLead;
		this.myManager = myManager;
		this.myLeader = myLeader;
		this.teamNum = teamNum;
		this.employeeNum = employeeNum;
		this.teamRoom = null;
		this.stats = stats;
	}
		
	private void question() throws InterruptedException{
		System.out.println(stats.getFormattedTime()+": Developer "+ teamNum +"-"+ employeeNum +" asks their lead developer a question.");
		if( rGen.nextInt(100)+1 <= 50 ) System.out.println(stats.getFormattedTime()+": Developer "+ teamNum +"-"+ employeeNum +" had their question answered.");
		else{
			myLeader.askManager(this);
			/*synchronized(this){
				System.out.println(teamNum + "-" + employeeNum + " waits");
				wait();
				System.out.println(teamNum + "-" + employeeNum + " woke up");
			}*/
		}
	}
	
	private void lunch() throws InterruptedException{
		lunch = rGen.nextInt(31 - arrival )+30;
		stats.put(0, 0, lunch, 0);
		System.out.println(stats.getFormattedTime()+": Developer "+ teamNum +"-"+ employeeNum +" took lunch for "+ lunch +" minutes.");
		Thread.sleep(lunch*10);
		System.out.println(stats.getFormattedTime()+": Developer "+ teamNum +"-"+ employeeNum +" returns from lunch.");
	}
	
	public void askManager(Employee dev) throws InterruptedException{
		System.out.println(stats.getFormattedTime()+": Developer "+ teamNum +"-"+ employeeNum +" takes a question to the manager.");
		myManager.askQuestion(this, dev);
		synchronized(this){
				wait();
			}
	}
	
	public boolean isLead(){
		return isLead;
	}
	
	public void run(){
		//TODO time stamps.
		stats.put(0, 480, 0, 0);
		arrival = rGen.nextInt(30);
		try {
			Thread.sleep(arrival*10);
			System.out.println(stats.getFormattedTime()+": Developer "+ teamNum +"-"+ employeeNum +" arrives at work");
			if( isLead ){
				manBarrier.await();
				Thread.sleep(150);
				while( teamBarrier.getNumberWaiting() != 3){
					
				}
				teamRoom.acquire();
				System.out.println(stats.getFormattedTime()+": Team "+ teamNum +" starts their morning meeting.");
			}
			teamBarrier.await();
			int start = stats.getTime();
			while( stats.getTime() < 15+start){
				Thread.sleep(5);
			}
			
			if( isLead ){ 
				System.out.println(stats.getFormattedTime()+": Team "+ teamNum +"'s meeting ends.");
				teamRoom.release();
			}
			
			boolean hadLunch = false;
			
			while( stats.getTime() < 480 ){
				int  action = rGen.nextInt(100)+1;
				if( action <= 5){
					if( !isLead ) question();
					else myManager.askQuestion(this);
				}else if( action <= 10 && stats.getTime() < 420 && !hadLunch ){
					lunch();
					hadLunch = true;
				}
				Thread.sleep(10);
			}

			boolean meeting = false;
			while( stats.getTime() < 540 ){ //end meeting
				int  action = rGen.nextInt(100)+1;
				if( (action <= 50 || stats.getTime() >= 495) && !meeting ){
					System.out.println(stats.getFormattedTime()+": Developer "+ teamNum +"-"+ employeeNum +" arrives at the afternoon meeting.");
					meeting = true;
					while( stats.getTime() < 510){
						Thread.sleep(10);
					}
					System.out.println(stats.getFormattedTime()+": Developer "+ teamNum +"-"+ employeeNum +" leaves the afternoon meeting.");
				}
				if( action <= 50 && stats.getTime() > (510 + arrival) && meeting){
					break;
				}
				Thread.sleep(10);
			}
			stats.put(0, 0, 0, 30);
			System.out.println(stats.getFormattedTime()+": Developer "+ teamNum +"-"+ employeeNum +" has left the office.");
					
			} catch (InterruptedException e) {} 
			catch (BrokenBarrierException e) {}
		}	
	
	public String toString()
	{
		return teamNum + "-" + employeeNum;
	}

}
